package com.wxx;


import com.sun.org.apache.bcel.internal.generic.NEW;

/**
 * @author: Jetwang
 * @date: 2022/3/20 20:02
 * @description: GenericArray 定义数组泛型类
 * @version: 1.0
 */
public class GenericArray<T> {
    private T[] data;
    private int size;

    /**
     * 默认容量为10
     */
    public GenericArray() {
        this(10);
    }

    /**
     * 构造函数，传入数组的容量
     * @param capacity
     */
    public GenericArray(int capacity) {
        data = (T[]) new Object[capacity];
        this.size = 0;
    }

    /**
     * 获取数组元素中个数
     * @return
     */
    public int getSize() {
        return size;
    }

    /**
     * 获取数组的容量
     * @return
     */
    public int getCapacity() {
        return data.length;
    }

    /**
     * 判断数组是否为空
     * @return
     */
    public boolean isEmpty() {
        return this.size == 0;
    }

    /**
     * 向数组中添加元素
     * @param e
     */
    public void addLast(T e) {
        /*if (size == data.length) {
            throw new IllegalArgumentException("AddLast failed, Array is full");
        }
        data[size] = e;
        size++;*/
        insert(size, e);
    }

    /**
     * 向数组最前面中添加元素
     * @param e
     */
    public void addFirst(T e) {
        insert(0, e);
    }

    /**
     * 插入元素
     * @param index
     * @param e
     */
    public void insert(int index, T e) {
        if (size == data.length) {
            // 扩容数组,扩容数组的2倍
            resize(2 * data.length);
        }
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("AddLast failed, Require index < 0 || index > size");
        }
        for (int i = size; i > index; i--) {
            // 元素往后移
            data[i] = data[i-1];
        }
        data[index] = e;
        size++;
    }

    /**
     * 扩容数组
     * @param newCapacity
     */
    private void resize(int newCapacity) {
        T[] newDate = (T[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newDate[i] = data[i];
        }
        data = newDate;
    }

    /**
     * 重写toString方法
     * @return
     */
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append(String.format("GenericArray: size= %d, capacity= %d\n", size, data.length));
        builder.append("[");
        for (int i = 0; i < size; i++) {
            builder.append(data[i]);
            if (i != size - 1) {
                builder.append(",");
            }
        }
        builder.append("]");
        return builder.toString();
    }

    /**
     * 获取索引位置元素
     * @param index
     * @return
     */
    T get(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("Get failed, index is illegal");
        }
        return data[index];
    }

    /**
     * 更新元素
     * @param index
     * @param e
     */
    void set(int index, T e) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("Updated failed, index is illegal");
        }
        data[index] = e;
    }

    /**
     * 查找数组是否包含某元素
     * @param e
     * @return
     */
    public boolean contains(T e) {
        for (int i = 0; i < size; i++) {
            if (data[i].equals(e)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 查找元素
     * @param e
     * @return
     */
    public int find(T e) {
        for (int i = 0; i < size; i++) {
            if (data[i].equals(e)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 删除指定位置元素,并返回删除的元素
     * @param index
     */
    public T remove(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("Removed failed, index is illegal");
        }
        T res = data[index];
        for (int i = index + 1; i < size; i++) {
            data[i-1] = data[i];
        }
        size--;
        data[size] = null;
        // 缩小容量
        if (size == data.length / 4 && data.length / 2 != 0) {
            resize(data.length / 2);
        }
        return res;
    }

    /**
     * 删除第一个元素
     * @return
     */
    public T removeFirst() {
        T res = remove(0);
        return res;
    }

    /**
     * 删除最后一个元素
     * @return
     */
    public T removeLast() {
        T res = remove(size-1);
        return res;
    }

    /**
     * 删除某个元素
     * @param e
     */
    public void removeElement(T e) {
        int index = find(e);
        if (index != -1) {
            remove(index);
        }
    }


}
